package com.zys.sac.core.helper;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.zys.sac.core.constant.RequestParam;
import org.springframework.security.core.userdetails.UserDetails;

import java.nio.charset.StandardCharsets;
import java.util.Date;

/**
 * token持久化接口
 *
 * Created by zhongjunkai on 2022/4/13.
 */
public interface TokenManager {

    String tokenFormat = "__sac:token:%s__";

    default String createCacheKey(String token) {
        JWTVerifier verifier = JWT.require(Algorithm.HMAC256(RequestParam.JWT_SECRET.getBytes(StandardCharsets.UTF_8))).build();
        DecodedJWT verify = verifier.verify(token);
        // 获取当前token中的用户名和角色权限信息（这里把角色和权限放到一个集合里了）
        String username = verify.getClaim(RequestParam.USERNAME).asString();
        return String.format(tokenFormat, username);
    }

    default String generateToken(UserDetails userDetails) {
        long now = System.currentTimeMillis();
        long expired = now + 3600 * 1000 * 24 * 365 * 10;
        JWTCreator.Builder builder = JWT.create()
                .withIssuedAt(new Date(now))
                .withExpiresAt(new Date(expired))
                .withClaim(RequestParam.USERNAME, userDetails.getUsername());
        //采用的加密算法以及秘钥签名字符串，这里的加密签名比较简单，在正式环境中可以采用比较复杂的签名字符串
        String token = builder.sign(Algorithm.HMAC256(RequestParam.JWT_SECRET.getBytes(StandardCharsets.UTF_8)));
        return token;
    }

    /**
     * 创建并保存token和用户信息
     *
     * @param userDetails
     * @return
     */
    String createAndSaveToken(UserDetails userDetails);

    /**
     * 创建并保存token和用户信息
     *
     * @param userDetails
     * @param expired
     * @return
     */
    String createAndSaveToken(UserDetails userDetails, long expired);

    /**
     * token续期
     *
     * @param token
     */
    void renewalToken(String token);

    /**
     * token续期
     *
     * @param token
     * @param expired
     */
    void renewalToken(String token, long expired);

    /**
     * 获取用户详情
     *
     * @param token
     * @return
     */
    Object getUserDetails(String token);

    /**
     * 将token缓存设置为失效
     *
     * @param token
     */
    void invalidToken(String token);

}
